"""
Base classes and data structures for Forward Error Correction (FEC).
"""

from abc import ABC, abstractmethod
from dataclasses import dataclass
from typing import List, Optional, Dict, Any, TYPE_CHECKING
import time
from ..logger_config import log_info, log_debug, log_warning, log_error, log_success, log_failure, log_progress, log_connection, log_media, log_stats

# 延迟导入以避免循环依赖
if TYPE_CHECKING:
    try:
        from ..rtp import RtpPacket
    except ImportError:
        from rtp import RtpPacket


@dataclass
class FecConfig:
    """FEC配置参数"""
    fec_type: str  # 'reed_solomon', 'xor', 'repetition'
    k: int  # 原始包数量
    n: int  # 总包数量（原始+冗余）
    repair_window_ms: int = 100  # 修复窗口时间
    enable_adaptive: bool = True  # 是否启用自适应FEC
    repetition_factor: int = 2  # 重复码的重复因子（仅用于repetition类型）
    
    def __post_init__(self):
        if self.fec_type == 'repetition':
            # 对于重复码，n应该是k的倍数
            if self.n % self.k != 0:
                self.n = self.k * self.repetition_factor


@dataclass
class FecPacket:
    """FEC包结构"""
    fec_payload_id: int
    repair_payload: bytes
    protected_sequence_numbers: List[int]
    fec_type: str
    timestamp: float = None
    
    def __post_init__(self):
        if self.timestamp is None:
            self.timestamp = time.time()


class BaseFecCodec(ABC):
    """FEC编解码器基类"""
    
    def __init__(self, config: FecConfig):
        self.config = config
        self.sequence_number = 0
        self.stats = {
            'encoded_packets': 0,
            'decoded_packets': 0,
            'recovered_packets': 0,
            'failed_recoveries': 0
        }
    
    @abstractmethod
    def encode(self, packets: List['RtpPacket']) -> List[FecPacket]:
        """编码原始RTP包生成FEC包"""
        pass
    
    @abstractmethod
    def decode(self, original_packets: List[Optional['RtpPacket']], 
               fec_packets: List[FecPacket]) -> List[Optional['RtpPacket']]:
        """使用FEC包修复丢失的原始包"""
        pass
    
    @abstractmethod
    def can_repair(self, lost_packets: List[int], 
                   available_fec_packets: List[FecPacket]) -> bool:
        """检查是否可以用可用FEC包修复丢失的包"""
        pass
    
    def get_stats(self) -> Dict[str, Any]:
        """获取统计信息"""
        return self.stats.copy()
    
    def reset_stats(self):
        """重置统计信息"""
        self.stats = {
            'encoded_packets': 0,
            'decoded_packets': 0,
            'recovered_packets': 0,
            'failed_recoveries': 0
        }


class FecPacketBuffer:
    """FEC包缓冲区"""
    
    def __init__(self, max_size: int = 1000):
        self.max_size = max_size
        self.packets: Dict[int, FecPacket] = {}
        self.original_packets: Dict[int, Optional[RtpPacket]] = {}
    
    def __len__(self):
        """返回FEC包数量"""
        return len(self.packets)
    
    def add_fec_packet(self, fec_packet: FecPacket):
        """添加FEC包"""
        if len(self.packets) >= self.max_size:
            # 移除最旧的包
            oldest_id = min(self.packets.keys())
            del self.packets[oldest_id]
        
        self.packets[fec_packet.fec_payload_id] = fec_packet
    
    def add_original_packet(self, sequence_number: int, packet: Optional['RtpPacket']):
        """添加原始包"""
        if len(self.original_packets) >= self.max_size:
            # 移除最旧的包
            oldest_seq = min(self.original_packets.keys())
            del self.original_packets[oldest_seq]
        
        self.original_packets[sequence_number] = packet
    
    def get_fec_packets(self) -> List[FecPacket]:
        """获取所有FEC包"""
        return list(self.packets.values())
    
    def get_original_packets(self, sequences: List[int]) -> List[Optional['RtpPacket']]:
        """获取指定序列号的原始包"""
        return [self.original_packets.get(seq) for seq in sequences]
    
    def clear(self):
        """清空缓冲区"""
        self.packets.clear()
        self.original_packets.clear()